# -*- encode: UTF-8 -*-

#states
state_input = 1
state_move = 2
state_catch = 3
state_eat = 4
state_over = 5

#pieces and player
piece_empty = 0
piece_p1 = 1
piece_p2 = 2
piece_p2_catch_p1 = 3
piece_p1_catch_p2 = 4

class pieceposition:
    def __init__(self):
        self.x = 0
        self.y = 0

class game:
    def __init__(self):
        self.curplayer = piece_p1
        self.state = state_input
        self.stateparam = 1

        self.ground = []
        for i in range(5):
            self.ground.append([0,0,0,0,0])

    #Functions
    def GetFullLineLengthOfPostion(self, pos):
        curpiece = self.ground[pos.x][pos.y]
        if curpiece == piece_empty:
            return 0

        #Horizontal
        full = True
        for i in range(5):
            if self.ground[i][pos.y] != curpiece:
                full = False
                break;
        if full:
            return 5

        #Vertical
        full = True
        for i in range(5):
            if self.ground[pos.x][i] != curpiece:
                full = False
                break;
        if full:
            return 5

        #two bevel line --- y/x=1
        b = pos.y - pos.x
        res = 0
        full = True
        lastres = 0
        for i in range(5):
            y = i + b
            if y>=0 and y < 5:
                if self.ground[i][y] != curpiece:
                    full = False
                    break
                else:
                    res += 1
        if full:
            lastres = res

        # y/x = -1
        b = pos.y + pos.x
        res = 0
        full = True
        for i in range(5):
            y = -i + b
            if y>=0 and y < 5:
                if self.ground[i][y] != curpiece:
                    full = False
                    break
                else:
                    res += 1
        if full and res > lastres:
            return res

        return lastres

    def SwapPlayer(self):
        self.curplayer = 1 if self.curplayer == 2 else 2

    def GetOtherPlayer(self):
        return 1 if self.curplayer == 2 else 2

    def IsGroundFull(self):
        for i in range(5):
            for j in range(5):
                if self.ground[i][j] == piece_empty:
                    return False
        return True

    def HasPiece(self, piece):
        for i in range(5):
            for j in range(5):
                if self.ground[i][j] == piece:
                    return True
        return False

    def RemoveCaughtPieces(self):
        for i in range(5):
            for j in range(5):
                if self.ground[i][j] > 2:
                    self.ground[i][j] = piece_empty

    def CanMove(self, curpos, tarpos):
        if curpos.x == tarpos.x:
            return curpos.y- tarpos.y == 1 or curpos.y - tarpos.y == -1
        elif curpos.y == tarpos.y:
            return curpos.x- tarpos.x == 1 or curpos.x - tarpos.x == -1
        return False

    def IsPieceMoveAble(self, x, y):
        curpos = pieceposition()
        curpos.x = x
        curpos.y = y
        tarpos = pieceposition()
        if x-1>=0:
            tarpos.x = x-1
            tarpos.y = y
            if self.CanMove(curpos, tarpos):
                return True
        if x+1<5:
            tarpos.x = x+1
            tarpos.y = y
            if self.CanMove(curpos, tarpos):
                return True
        if y-1>=0:
            tarpos.x = x
            tarpos.y = y-1
            if self.CanMove(curpos, tarpos):
                return True
        if y+1<5:
            tarpos.x = x
            tarpos.y = y+1
            if self.CanMove(curpos, tarpos):
                return True
        return False


    #Operations
    def SetPiece(self, tarpos):
        if self.state == state_input and self.ground[tarpos.x][tarpos.y] == piece_empty:
            self.ground[tarpos.x][tarpos.y] = self.curplayer

            linked = self.GetFullLineLengthOfPostion(tarpos)
            if linked > 2:
                if self.HasPiece(self.GetOtherPlayer()):
                    self.state = state_catch
                    self.stateparam = linked - 2
                else:
                    self.state = state_over
            else:
                self.SwapPlayer()
                if self.IsGroundFull():
                    self.state = state_move
                    self.RemoveCaughtPieces()

    def Catch(self, tarpos):
        if self.state == state_catch and self.ground[tarpos.x][tarpos.y] == self.GetOtherPlayer():
            self.ground[tarpos.x][tarpos.y] += 2
            self.stateparam -= 1

            if not self.HasPiece(self.GetOtherPlayer()):
                self.state = state_over
            elif self.stateparam == 0:
                self.SwapPlayer()
                if self.IsGroundFull():
                    self.state = state_move
                    self.RemoveCaughtPieces()
                else:
                    self.state = state_input

    def Move(self, curpos, tarpos):
        if self.state == state_move and self.ground[curpos.x][curpos.y] == self.curplayer and self.ground[tarpos.x][tarpos.y] == piece_empty and self.CanMove(curpos, tarpos):
            self.ground[curpos.x][curpos.y] = piece_empty
            self.ground[tarpos.x][tarpos.y] = self.curplayer

            linked = self.GetFullLineLengthOfPostion(tarpos)
            if linked > 2:
                self.state = state_eat
                self.stateparam = linked - 2
            else:
                self.SwapPlayer()

    def IsSomePieceMoveAble(self):
        for i in range(5):
            for k in range(5):
                if self.ground[i][k] == self.curplayer:
                    if self.IsPieceMoveAble(i, k):
                        return True
        return False

    def Eat(self, tarpos):
        if self.state == state_eat and self.ground[tarpos.x][tarpos.y] == self.GetOtherPlayer():
            self.ground[tarpos.x][tarpos.y] = piece_empty
            self.stateparam -= 1

            if not self.HasPiece(self.GetOtherPlayer()):
                self.state = state_over
            elif self.stateparam == 0:
                self.SwapPlayer()
                self.state = state_move


